// Import modules
var grid = require('./grid.js');
var converter = require('./converter.js');

var mapsFuncs = require('../DAO/schemaMap.js');
var tilesFuncs = require('../DAO/schemaTile.js');
var herosFuncs = require('../DAO/schemaHero.js');
var cropsFuncs = require('../DAO/schemaCrop.js');
var buildingsFuncs = require('../DAO/schemaBuilding.js');

var myUser = require('./authentication.js').curUser;

// io.sockets.emit --> to everyone
// socket.broadcast.emit --> to everyone except current client

var gSocket = null;
var gIo = null;

function events(io, socket){

    socket.on('cl_hi', function() {
        console.log(' --- HI FROM CLIENT ---');
    })

    socket.on('cl_hero_update', updateHero);
    socket.on('cl_tile_update', function(cl_tile) { updateTile(socket, cl_tile) });

    //events upd sur crop & buildings aussi use pour la creation de ceux ci
    socket.on('cl_crop_update', function(cl_crop) { updateOrCreateCrop(socket, cl_crop) });
    //update les timers des crops pour un héros spécifique
    //TODO stocker timeRemaining dans la RAM du serv et store en DB sur le disconnect event ?
    socket.on('cl_cropsTimers_update', updateCropsTimersForHeroId);
    socket.on('cl_crop_deleted', function(cl_cropPos) {
        console.log('sending delete crop to all clients ?');
        io.sockets.emit('sv_crop_deleted', cl_cropPos);
    })

    socket.on('cl_building_update', function(cl_building) { updateOrCreateBuilding(socket, cl_building) });

    socket.on('cl_move_event', function(cl_hero, cl_hero_steps) {
        socket.broadcast.emit('sv_move_event', cl_hero, cl_hero_steps);
    });

    socket.on('cl_proceedStep_event', proceedStep);

    socket.on('cl_leave_event', heroLeave);

//    socket.emit('sv_test_receive', 'socket.emit');
//    socket.broadcast.emit('sv_test_receive', 'socket.broadcast.emit');
}

function heroLeave(cl_hero) {
    console.log('--- HERO LEAVING ---');
    console.log(cl_hero);
}

//INIT MAP IN DB & GAME STARTING EVENT
function tryPopulateMap() {
    mapsFuncs.getMap(function(map) {
        if(map == null) {
            grid.initMap();
        }
        else console.log('map found, cancelling populateMap()...');
    })
}

function startGame(socket, username){
    mapsFuncs.getMap(function(map) {
        herosFuncs.getAllHeros(function (heros){
            socket.emit('sv_game_loaded', map, heros, 'hero_'+username);
//            socket.emit('sv_logged', myUser.heros[0]);
        });
    });
}

// CLIENT SIDE EVENT

//On save la new pos du héros
//(sent à chaque fois qu'un héros fais une step, c à d avance d'une tile)
function proceedStep(cl_hero, cl_newPosRC) {
    herosFuncs.getHeroById(cl_hero.id, function(db_hero) {
        db_hero.setPosition( cl_newPosRC.row,  cl_newPosRC.col);
        db_hero.save(function(err) {
            if(err) console.log(err.message);
//            else console.log('hero pos updated to '+cl_newPosRC.row+','+cl_newPosRC.col);
        });
    });
}

function updateTile(socket, cl_tile) {
    mapsFuncs.getMap(function(map) {
        tilesFuncs.updTile(map, cl_tile, function(sv_tile) {
            //quand la tile est save on send aux autres users la tile updated
            socket.broadcast.emit('sv_tile_update', sv_tile);
        });
    });
}

function updateOrCreateBuilding(socket, cl_building) {
    herosFuncs.getHeroById(cl_building.heroId, function(hero) {
        var buildingIndex = buildingsFuncs.isBuildingFound(hero, cl_building);

        if(buildingIndex != null) {
            buildingsFuncs.updBuilding(hero, cl_building, buildingIndex, function(sv_building) {
                //nothing ?
            });
        }
        else {
            buildingsFuncs.createBuilding(hero, cl_building, function(sv_building){
                socket.broadcast.emit('sv_building_created', sv_building);
            })
        }
    })
}

function updateOrCreateCrop(socket, cl_crop) {
    herosFuncs.getHeroById(cl_crop.heroId, function(hero) {
        var cropIndex = cropsFuncs.isCropFound(hero, cl_crop);

        //Si la crop est trouvée, on l'update
        if(cropIndex != null) {
            cropsFuncs.updCrop(hero, cl_crop, cropIndex, function(sv_crop) {
                socket.broadcast.emit('sv_crop_updated', sv_crop);
            })
        }
        //Sinon, on la créer
        else{
            cropsFuncs.createCrop(hero, cl_crop, function(sv_crop) {
                socket.broadcast.emit('sv_crop_created', sv_crop);
            })
        }
    })
}

//update les timers des crops pour un héros spécifique
function updateCropsTimersForHeroId(heroId, crops) {
    herosFuncs.getHeroById(heroId, function(hero) {
        cropsFuncs.updCropsTimers(hero, crops);
    })
}

function updateHero(cl_hero) {
    herosFuncs.getHeroById(cl_hero.id, function(hero) {
        herosFuncs.updHero(hero, cl_hero);
    });
}

//
//function updateHero(hero, id_user){
//    var hero_doc = converter.heroToDoc(hero);
//
//    User.findById(id_user, function(err, user){
//        if(!err){
//            var h = user.heros[0];
//            h.gold = hero_doc.gold;
//            h.level = hero_doc.level;
//            h.position = hero_doc.position;
//
//            user.markModified('heros');
//            user.save(function(err){
//                if (!err) console.log('Hero updated');
//                else console.log('Error: ' + err);
//            })
//        }
//    })
//}

exports.startGame = startGame;
exports.tryPopulateMap = tryPopulateMap;
exports.events = events;